package com.kwdb.importtool.core;

import com.kwdb.importtool.model.SQLStatement;
import com.kwdb.importtool.util.LoggerUtil;
import lombok.Data;
import org.slf4j.Logger;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * SQL语法转换器 - 针对KWDB优化
 */
@Data
public class SQLConverter {
    private static final Logger logger = LoggerUtil.getLogger(SQLConverter.class.getName());

    // 忽略的语句类型
    private Set<String> ignoredStatements;

    // KWDB关键字列表，需要加引号
    private Set<String> kwdbKeywords;

    // 新增：KaiwuDB引擎类型枚举（区分关系引擎/时序引擎）
    public enum KaiwuEngineType {
        RELATIONAL_ENGINE,
    }

    // 新增：默认引擎类型（保持原有逻辑兼容性，默认用关系引擎）
    private KaiwuEngineType defaultEngineType = KaiwuEngineType.RELATIONAL_ENGINE;

    public SQLConverter() {
        initializeMappings();
    }

    // 新增：支持指定默认引擎类型的构造器
    public SQLConverter(KaiwuEngineType defaultEngineType) {
        initializeMappings();
        this.defaultEngineType = defaultEngineType;
    }

    /**
     * 初始化配置
     */
    private void initializeMappings() {
        // 忽略的语句类型
        ignoredStatements = new HashSet<>(Arrays.asList(
                "SET NAMES", "SET FOREIGN_KEY_CHECKS", "SET CHARACTER SET",
                "SET sql_mode", "SET time_zone"
        ));

        // KWDB关键字列表
        kwdbKeywords = new HashSet<>(Arrays.asList(
                "tag", "tags", "key", "keys", "value", "values", "user", "users",
                "group", "groups", "order", "index", "primary", "foreign",
                "check", "constraint", "default", "null", "not", "and", "or",
                "like", "between", "in", "is", "exists", "all", "any", "some",
                "asc", "desc", "limit", "offset", "distinct", "unique", "primary",
                "foreign", "references", "cascade", "restrict", "set", "null",
                "true", "false", "current_date", "current_time", "current_timestamp"
        ));
    }

    /**
     * 转换SQL语句
     */
    public SQLStatement convert(SQLStatement original) {
        // 修改：调用带默认引擎的重载方法
        return convert(original, this.defaultEngineType);
    }

    // 新增：支持指定引擎类型的SQL转换方法
    public SQLStatement convert(SQLStatement original, KaiwuEngineType engineType) {
        SQLStatement converted = new SQLStatement();
        converted.setOriginalSQL(original.getOriginalSQL());
        converted.setStatementType(original.getStatementType());
        converted.setLineNumber(original.getLineNumber());

        try {
            // 修改：调用带引擎参数的convertSQL方法
            String convertedSQL = convertSQL(original.getOriginalSQL(), engineType);
            converted.setConvertedSQL(convertedSQL);
            converted.setConversionSuccess(true);

            if (!original.getOriginalSQL().equals(convertedSQL)) {
                logger.debug("Converted: {} -> {}", original.getOriginalSQL(), convertedSQL);
            }

        } catch (Exception e) {
            logger.warn("Failed to convert SQL: {}", original.getOriginalSQL(), e);
            converted.setConvertedSQL(original.getOriginalSQL());
            converted.setConversionSuccess(false);
            converted.setConversionError(e.getMessage());
        }

        return converted;
    }

    // 新增：支持指定引擎类型的SQL语法转换方法
    private String convertSQL(String originalSQL, KaiwuEngineType engineType) {
        if (originalSQL == null || originalSQL.trim().isEmpty()) {
            return originalSQL;
        }

        String sql = originalSQL.trim();
        String upperSQL = sql.toUpperCase();

        // 检查是否应该忽略此语句
        if (shouldIgnoreStatement(sql)) {
            logger.debug("Ignoring statement: {}", sql);
            return "";
        }

        // 根据SQL类型进行转换（修改：调用带引擎参数的转换方法）
        if (upperSQL.startsWith("CREATE TABLE")) {
            return convertCreateTable(sql, engineType);
        } else if (upperSQL.startsWith("INSERT INTO")) {
            return convertInsertStatement(sql);
        } else if (upperSQL.startsWith("DROP TABLE")) {
            return convertDropTable(sql);
        } else if (upperSQL.startsWith("ALTER TABLE")) {
            return convertAlterTable(sql);
        } else {
            return convertGenericSQL(sql);
        }
    }

    /**
     * 转换CREATE TABLE语句
     */
    private String convertCreateTable(String sql, KaiwuEngineType engineType) {
        // 移除反引号
        String cleanedSQL = removeBackticks(sql);

        // 移除FULLTEXT KEY定义
        cleanedSQL = cleanedSQL.replaceAll("(?i)FULLTEXT\\s+KEY\\s+\\w+\\s*\\([^)]+\\)", "");

        // 提取表名
        String tableName = extractTableName(cleanedSQL);

        // 构建基本的CREATE TABLE语句
        StringBuilder result = new StringBuilder();
        result.append("CREATE TABLE ");
        if (cleanedSQL.toUpperCase().contains("IF NOT EXISTS")) {
            result.append("IF NOT EXISTS ");
        }
        // 表名关键字转义
        result.append(escapeKeyword(tableName)).append(" (\n");

        // 提取列定义
        String columnDefs = extractColumnDefinitions(cleanedSQL);
        // 修改：调用带引擎参数的列定义转换方法
        String convertedColumns = convertColumnDefinitions(columnDefs, engineType);
        result.append(convertedColumns);

        result.append("\n)");

        return removeCommaIfEndsWithCommaAndParenthesis(result.toString());
    }
    public static String removeCommaIfEndsWithCommaAndParenthesis(String result) {
        // 处理null情况
        if (result == null) {
            return null;
        }

        int length = result.length();
        int lastParenthesisIndex = length - 1;

        // 找到最后一个非空白字符的位置（应该是右括号）
        while (lastParenthesisIndex >= 0 && Character.isWhitespace(result.charAt(lastParenthesisIndex))) {
            lastParenthesisIndex--;
        }

        // 如果不是以右括号结尾，直接返回
        if (lastParenthesisIndex < 0 || result.charAt(lastParenthesisIndex) != ')') {
            return result;
        }

        // 保存原有的功能：删除紧挨着右括号的最后一个逗号
        int lastCommaIndex = lastParenthesisIndex - 1;
        while (lastCommaIndex >= 0 && Character.isWhitespace(result.charAt(lastCommaIndex))) {
            lastCommaIndex--;
        }

        boolean hasCommaBeforeParenthesis = (lastCommaIndex >= 0 && result.charAt(lastCommaIndex) == ',');

        // 新增功能：从右括号前开始，向前找到第一个非逗号、非空白字符
        int firstNonCommaBeforeParenthesis = lastParenthesisIndex - 1;
        while (firstNonCommaBeforeParenthesis >= 0) {
            char c = result.charAt(firstNonCommaBeforeParenthesis);
            if (!Character.isWhitespace(c) && c != ',') {
                break;
            }
            firstNonCommaBeforeParenthesis--;
        }

        // 如果存在需要删除的逗号
        if (firstNonCommaBeforeParenthesis < lastParenthesisIndex - 1) {
            StringBuilder sb = new StringBuilder();

            // 第一部分：从开始到第一个非逗号字符
            sb.append(result.substring(0, firstNonCommaBeforeParenthesis + 1));

            // 第二部分：处理中间部分 - 删除所有逗号但保留其他字符（包括空格）
            for (int i = firstNonCommaBeforeParenthesis + 1; i < lastParenthesisIndex; i++) {
                char c = result.charAt(i);
                if (c != ',') {
                    sb.append(c);
                }
            }

            // 第三部分：添加右括号及之后的内容
            sb.append(result.substring(lastParenthesisIndex));

            return sb.toString();
        }

        // 如果没有连续的逗号需要删除，但存在紧挨着右括号的单个逗号，使用原有逻辑
        if (hasCommaBeforeParenthesis) {
            return result.substring(0, lastCommaIndex) + result.substring(lastCommaIndex + 1);
        }

        return result;
    }

    // 新增：支持指定引擎类型的列定义转换方法
    private String convertColumnDefinitions(String columnDefs, KaiwuEngineType engineType) {
        List<String> convertedColumns = new ArrayList<>();
        List<String> parts = splitColumnDefinitions(columnDefs);

        for (String part : parts) {
            String trimmed = part.trim();
            if (trimmed.isEmpty()) continue;

            if (trimmed.toUpperCase().contains("SPATIAL KEY")) {
                continue;
            }

            if (isColumnDefinition(trimmed)) {
                // 修改：调用带引擎参数的单个列转换方法
                convertedColumns.add(convertColumnDefinition(trimmed, engineType));
            } else if (trimmed.toUpperCase().startsWith("PRIMARY KEY")) {
                convertedColumns.add(convertPrimaryKey(trimmed));
            } else if (trimmed.toUpperCase().startsWith("UNIQUE KEY") || trimmed.toUpperCase().startsWith("UNIQUE")) {
                convertedColumns.add(convertUniqueConstraint(trimmed));
            } else if (trimmed.toUpperCase().startsWith("CHECK")) {
                convertedColumns.add(convertCheckConstraint(trimmed));
            } else if (trimmed.toUpperCase().startsWith("CONSTRAINT")) {
                convertedColumns.add(convertNamedConstraint(trimmed));
            }
            // 注意：索引定义在KWDB中需要在CREATE TABLE外部单独创建，所以这里跳过
            // 外键约束需要在表创建后通过ALTER TABLE添加
        }

        return String.join(",\n", convertedColumns);
    }


    //支持指定引擎类型的单个列定义转换方法
    private String convertColumnDefinition(String columnDef, KaiwuEngineType engineType) {
        String cleaned = columnDef;

        // 1. 移除反引号
        cleaned = removeBackticks(cleaned);

        // 2. 处理关键字列名 - 先处理列名
        cleaned = escapeKeywordsInColumnName(cleaned);

        // 3. 移除注释
        cleaned = removeComment(cleaned);

        // 4. 移除字符集和排序规则
        cleaned = removeCharsetAndCollate(cleaned);

        // 5. 转换数据类型（修改：调用带引擎参数的convertDataType）
        String originalColumnDef = cleaned; // 保存原始列定义用于ENUM处理
        cleaned = convertDataType(cleaned, engineType);

        // 6. 处理AUTO_INCREMENT
        cleaned = cleaned.replaceAll("(?i)AUTO_INCREMENT", "");

        // 7. 处理默认值 - 使用更安全的方法
        cleaned = convertDefaultValueSafely(cleaned);

        // 8. 移除 ON UPDATE CURRENT_TIMESTAMP
        cleaned = cleaned.replaceAll("(?i)ON UPDATE CURRENT_TIMESTAMP", "");

        // 9. 处理布尔值
        cleaned = cleaned.replaceAll("b'0'", "'0'");
        cleaned = cleaned.replaceAll("b'1'", "'1'");

        // 10. 移除 USING BTREE 等索引类型
        cleaned = cleaned.replaceAll("(?i)USING\\s+\\w+", "");

        // 11. 如果是ENUM类型，添加CHECK约束
        if (originalColumnDef.toLowerCase().contains("enum")) {
            cleaned = addEnumCheckConstraint(cleaned, originalColumnDef);
        }

        // 12. 清理多余的空格
        cleaned = cleaned.replaceAll("\\s+", " ").trim();

        return cleaned;
    }

    /**
     * 为ENUM转换后的列添加CHECK约束
     */
    private String addEnumCheckConstraint(String convertedColumnDef, String originalColumnDef) {
        // 提取列名
        String columnName = extractColumnName(convertedColumnDef);

        // 提取ENUM值列表
        List<String> enumValues = extractEnumValuesFromColumnDef(originalColumnDef);
        if (enumValues.isEmpty()) {
            return convertedColumnDef;
        }

        // 构建CHECK约束条件
        String checkCondition = buildEnumCheckCondition(columnName, enumValues);

        // 将CHECK约束添加到列定义中
        return convertedColumnDef + " CHECK (" + checkCondition + ")";
    }

    /**
     * 从原始列定义中提取ENUM值
     */
    private List<String> extractEnumValuesFromColumnDef(String columnDef) {
        List<String> values = new ArrayList<>();

        // 匹配ENUM('value1','value2',...)
        Pattern pattern = Pattern.compile("enum\\s*\\(([^)]+)\\)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(columnDef);

        if (matcher.find()) {
            String valuesStr = matcher.group(1);
            // 分割逗号分隔的值，考虑引号内的逗号
            Pattern valuePattern = Pattern.compile("'([^']*)'");
            Matcher valueMatcher = valuePattern.matcher(valuesStr);

            while (valueMatcher.find()) {
                values.add(valueMatcher.group(1));
            }
        }

        return values;
    }

    /**
     * 构建ENUM的CHECK约束条件
     */
    private String buildEnumCheckCondition(String columnName, List<String> enumValues) {
        // 构建 IN ('value1','value2',...) 条件
        String inClause = enumValues.stream()
                .map(value -> "'" + value.replace("'", "''") + "'")
                .collect(Collectors.joining(","));

        return columnName + " IN (" + inClause + ")";
    }

    /**
     * 转换数据类型
     */
    private String convertDataType(String columnDef, KaiwuEngineType engineType) {
        // 提取列定义中的类型部分
        String typePart = extractTypePartFromColumnDef(columnDef);
        if (typePart == null || typePart.isEmpty()) {
            return columnDef; // 无法提取类型时返回原定义
        }

        // 预处理类型：转小写、去空格
        String lowerType = typePart.trim().toLowerCase();
        // 提取核心类型（如 "tinyint(1) unsigned" -> "tinyint"）
        String baseType = extractBaseType(lowerType);
        // 判断是否包含unsigned修饰
        boolean isUnsigned = lowerType.contains("unsigned");
        // 提取类型长度（如 "tinyint(1)" -> 1）
        Integer length = extractLength(lowerType);

        String kaiwuType = typePart; // 默认保留原类型

        // 数据类型映射逻辑
        switch (baseType) {
            case "boolean":
                kaiwuType = "bool";
                break;
            case "tinyint":
                // tinyint(1)视为bool，其他视为int2
                //根据文档测试错误！先将tinyint(1)视为int2
                if (length != null && length == 1) {
//                    kaiwuType = "bool";
                    kaiwuType = "int2";
                } else {
                    kaiwuType = isUnsigned ? "int4" : "int2";
                }
                break;
            case "smallint":
                kaiwuType = isUnsigned ? "int4" : "int2";
                break;
            case "int":
            case "integer":
                kaiwuType = isUnsigned ? "int8" : "int4";
                break;
            case "mediumint":
                kaiwuType = "int4";
                break;
            case "bigint":
                if (isUnsigned) {
                    kaiwuType = (engineType == KaiwuEngineType.RELATIONAL_ENGINE) ? "numeric(20)" : "int8";
                } else {
                    kaiwuType = "int8";
                }
                break;
            case "decimal":
                kaiwuType = (engineType == KaiwuEngineType.RELATIONAL_ENGINE) ? "decimal" : "float8";
                break;
            case "double":
                kaiwuType = "float8";
                break;
            case "float":
                kaiwuType = "float4";
                break;
            case "date":
            case "datetime":
            case "timestamp":
                kaiwuType = "timestamp";
                break;
            case "time":
                kaiwuType = (engineType == KaiwuEngineType.RELATIONAL_ENGINE) ? "time" : "timestamp";
                break;
            case "char":
                // 保留长度信息：char(20) -> char(20)
                if (typePart.contains("(")) {
                    kaiwuType = typePart;
                } else {
                    kaiwuType = "char";
                }
                break;
            case "varchar":
                // 保留长度信息：varchar(255) -> varchar(255)
                if (typePart.contains("(")) {
                    kaiwuType = typePart;
                } else {
                    kaiwuType = "varchar";
                }
                break;
            case "binary":
                kaiwuType = (engineType == KaiwuEngineType.RELATIONAL_ENGINE) ? "bytea" : "varbytes";
                break;
            case "varbinary":
            case "long varbinary":
                kaiwuType = "varbytes";
                break;
            case "blob":
            case "mediumblob":
                kaiwuType = (engineType == KaiwuEngineType.RELATIONAL_ENGINE) ? "bytes" : "varbytes";
                break;
            case "longtext":
                kaiwuType = "text";
                break;
            case "json":
//                kaiwuType = (engineType == KaiwuEngineType.RELATIONAL_ENGINE) ? "json" : "nvarchar";
                kaiwuType = (engineType == KaiwuEngineType.RELATIONAL_ENGINE) ? "text" : "nvarchar";
                break;
            case "geometry":
                kaiwuType = "text";
                break;
            case "year":
                kaiwuType = "int2";
                break;
            case "enum":
                // ENUM类型特殊处理：转换为VARCHAR并添加CHECK约束
                kaiwuType = convertEnumType(columnDef, typePart);
                break;
            case "set":
                // SET类型特殊处理：转换为text[]并添加CHECK约束 后记 暂时取消 insert有问题
                kaiwuType = "varchar";
                break;
            default:
                // 对于未知类型，直接使用原类型但移除长度限制
                kaiwuType = removeLengthIfNeeded(baseType);
                break;
        }

        // 将原列定义中的类型部分替换为KaiwuDB类型
        // 使用更精确的替换，避免替换列名等其他部分
        return columnDef.replaceAll("(?i)(?<=\\s)" + Pattern.quote(typePart) + "(?=\\s|$)", kaiwuType);
    }

    /**
     * 转换SET类型为text[]并生成CHECK约束
     */
    private String convertSetType(String columnDef, String setTypePart) {
        // 提取SET的值列表
        List<String> setValues = extractSetValues(setTypePart);
        if (setValues.isEmpty()) {
            return "text[]"; // 默认返回数组类型
        }

        // 构建CHECK约束条件
        String checkCondition = buildSetCheckCondition(extractColumnName(columnDef), setValues);

        // 返回类型定义加上CHECK约束
        return "text[] CHECK (" + checkCondition + ")";
    }


    /**
     * 从SET类型定义中提取值列表
     */
    private List<String> extractSetValues(String setTypePart) {
        List<String> values = new ArrayList<>();

        // 匹配SET('value1','value2',...)
        Pattern pattern = Pattern.compile("set\\s*\\(([^)]+)\\)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(setTypePart);

        if (matcher.find()) {
            String valuesStr = matcher.group(1);
            // 分割逗号分隔的值，考虑引号内的逗号
            Pattern valuePattern = Pattern.compile("'([^']*)'");
            Matcher valueMatcher = valuePattern.matcher(valuesStr);

            while (valueMatcher.find()) {
                values.add(valueMatcher.group(1));
            }
        }

        return values;
    }

    /**
     * 构建SET的CHECK约束条件
     */
    private String buildSetCheckCondition(String columnName, List<String> setValues) {
        // 构建 <@ ARRAY['value1','value2',...] 条件
        String arrayClause = setValues.stream()
                .map(value -> "'" + value.replace("'", "''") + "'")
                .collect(Collectors.joining(","));

        return columnName + " <@ ARRAY[" + arrayClause + "]";
    }


    /**
     * 转换ENUM类型为VARCHAR并生成CHECK约束
     */
    private String convertEnumType(String columnDef, String enumTypePart) {
        // 提取ENUM的值列表
        List<String> enumValues = extractEnumValues(enumTypePart);
        if (enumValues.isEmpty()) {
            return "varchar(50)"; // 默认长度
        }

        // 计算最大值的长度，用于确定VARCHAR长度
        int maxLength = enumValues.stream()
                .mapToInt(String::length)
                .max()
                .orElse(50);

        // VARCHAR长度至少为1，加上一些缓冲
        int varcharLength = Math.max(maxLength + 2, 10);

        return "varchar(" + varcharLength + ")";
    }

    /**
     * 提取ENUM类型的值列表
     */
    private List<String> extractEnumValues(String enumTypePart) {
        List<String> values = new ArrayList<>();

        // 匹配ENUM('value1','value2',...)中的值
        Pattern pattern = Pattern.compile("enum\\s*\\(([^)]+)\\)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(enumTypePart);

        if (matcher.find()) {
            String valuesStr = matcher.group(1);
            // 分割逗号分隔的值，考虑引号内的逗号
            Pattern valuePattern = Pattern.compile("'([^']*)'");
            Matcher valueMatcher = valuePattern.matcher(valuesStr);

            while (valueMatcher.find()) {
                values.add(valueMatcher.group(1));
            }
        }

        return values;
    }

    /**
     * 移除类型长度限制（对于KaiwuDB不支持的类型长度）
     */
    private String removeLengthIfNeeded(String type) {
        // 对于KaiwuDB不支持长度限制的类型，移除长度部分
        if (type.matches("(tinyint|smallint|mediumint|int|integer|bigint|float|double|bool).*")) {
            return type.replaceAll("\\([^)]+\\)", "");
        }
        return type;
    }

    //从列定义中提取类型部分（辅助方法）
    private String extractTypePartFromColumnDef(String columnDef) {
        // 修改后的正则表达式，增加对set类型的支持
        Pattern pattern = Pattern.compile(
                "^\\s*[`\"']?\\w+[`\"']?\\s+" +
                        "([a-zA-Z]+\\(\\d+\\)(?:\\s+unsigned)?(?:\\s+zerofill)?|" +  // 带长度的类型
                        "[a-zA-Z]+(?:\\s+unsigned)?(?:\\s+zerofill)?|" +             // 不带长度的类型
                        "enum\\s*\\([^)]+\\)|" +                                     // enum类型
                        "set\\s*\\([^)]+\\))(?:\\s|$)",                              // 新增set类型支持
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher = pattern.matcher(columnDef);

        if (matcher.find()) {
            return matcher.group(1).trim();
        }

        // 备选方案保持不变
        String[] parts = columnDef.trim().split("\\s+");
        if (parts.length >= 2) {
            // 检查第二部分是否是有效的数据类型
            String possibleType = parts[1].toLowerCase();
            if (possibleType.matches("^(tinyint|smallint|mediumint|int|integer|bigint|decimal|numeric|float|double|real|bit|date|time|timestamp|datetime|year|char|varchar|binary|varbinary|tinyblob|blob|mediumblob|longblob|tinytext|text|mediumtext|longtext|enum|set|json|geometry).*")) {
                return parts[1];
            }
        }

        logger.debug("无法从列定义中提取数据类型: {}", columnDef);
        return null;
    }

    // 新增：提取核心类型（去除长度、unsigned修饰）（辅助方法）
    private String extractBaseType(String type) {
        return type.replaceAll("\\(.*?\\)", "") // 去除括号及内容（如 "(1)"）
                .replace("unsigned", "")       // 去除unsigned
                .trim();
    }

    // 新增：提取类型中的长度数字（辅助方法）
    private Integer extractLength(String type) {
        Pattern pattern = Pattern.compile("\\((\\d+)\\)");
        Matcher matcher = pattern.matcher(type);
        if (matcher.find()) {
            try {
                return Integer.parseInt(matcher.group(1));
            } catch (NumberFormatException e) {
                logger.debug("Failed to parse type length: {}", type, e);
            }
        }
        return null;
    }

    /**
     * 批量转换SQL语句
     */
    public List<SQLStatement> convertBatch(List<SQLStatement> statements) {
        // 修改：调用带默认引擎的重载方法
        return convertBatch(statements, this.defaultEngineType);
    }

    // 新增：支持指定引擎类型的批量转换方法
    public List<SQLStatement> convertBatch(List<SQLStatement> statements, KaiwuEngineType engineType) {
        List<SQLStatement> converted = new ArrayList<>();

        for (SQLStatement statement : statements) {
            // 修改：调用带引擎参数的convert方法
            SQLStatement result = convert(statement, engineType);
            if (result.getConvertedSQL() != null && !result.getConvertedSQL().trim().isEmpty()) {
                converted.add(result);
            }
        }

        return converted;
    }

    /**
     * 检查是否应该忽略此语句
     */
    private boolean shouldIgnoreStatement(String sql) {
        String upperSQL = sql.toUpperCase();
        for (String ignored : ignoredStatements) {
            if (upperSQL.startsWith(ignored)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 提取表名
     */
    private String extractTableName(String sql) {
        // 优化表名提取正则，支持更多格式的表名
        Pattern pattern = Pattern.compile("CREATE TABLE\\s+(?:IF NOT EXISTS\\s+)?([^\\s(]+)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(sql);
        if (matcher.find()) {
            return matcher.group(1).trim();
        }
        return "unknown_table";
    }

    /**
     * 提取列定义部分
     */
    private String extractColumnDefinitions(String sql) {
        int start = sql.indexOf('(');
        int end = findMatchingParenthesis(sql, start);
        if (start == -1 || end == -1) {
            return "";
        }
        return sql.substring(start + 1, end);
    }

    /**
     * 处理关键字列名 - 为关键字列名添加双引号
     */
    private String escapeKeywordsInColumnName(String columnDef) {
        String[] parts = columnDef.split("\\s+", 2);
        if (parts.length == 0) return columnDef;

        String columnName = parts[0].replaceAll("[\"']", "");

        if (kwdbKeywords.contains(columnName.toLowerCase())) {
            String escapedColumnName = "\"" + columnName + "\"";
            if (parts.length > 1) {
                return escapedColumnName + " " + parts[1];
            } else {
                return escapedColumnName;
            }
        }

        return columnDef;
    }

    /**
     * 移除字符集和排序规则
     */
    private String removeCharsetAndCollate(String columnDef) {
        String cleaned = columnDef;
        cleaned = cleaned.replaceAll("(?i)CHARACTER SET\\s+\\w+", "");
        cleaned = cleaned.replaceAll("(?i)COLLATE\\s+\\w+", "");
        cleaned = cleaned.replaceAll("(?i)\\butf8mb4\\b", "");
        cleaned = cleaned.replaceAll("(?i)\\butf8\\b", "");
        cleaned = cleaned.replaceAll("(?i)\\blatin1\\b", "");
        return cleaned;
    }

    /**
     * 移除注释
     */
    private String removeComment(String columnDef) {
        return columnDef.replaceAll("(?i)COMMENT\\s+'.*?'", "").trim();
    }

    /**
     * 转换默认值 - 安全版本，正确处理字符串
     */
    private String convertDefaultValueSafely(String columnDef) {
        StringBuilder result = new StringBuilder();
        boolean inString = false;
        char stringChar = '\'';

        for (int i = 0; i < columnDef.length(); i++) {
            char c = columnDef.charAt(i);

            if (inString) {
                result.append(c);
                if (c == stringChar) {
                    if (i > 0 && columnDef.charAt(i-1) == '\\') {
                        continue;
                    }
                    inString = false;
                }
            } else {
                if (c == '\'' || c == '"') {
                    inString = true;
                    stringChar = c;
                    result.append(c);
                } else {
                    if (i < columnDef.length() - 12 &&
                            columnDef.substring(i, i + 12).equalsIgnoreCase("NOW()")) {
                        result.append("CURRENT_TIMESTAMP");
                        i += 11;
                    } else if (i < columnDef.length() - 21 &&
                            columnDef.substring(i, i + 21).equalsIgnoreCase("CURRENT_TIMESTAMP()")) {
                        result.append("CURRENT_TIMESTAMP");
                        i += 20;
                    } else {
                        result.append(c);
                    }
                }
            }
        }

        return result.toString();
    }

    /**
     * 转换主键约束
     */
    private String convertPrimaryKey(String pkDef) {
        String converted = removeBackticks(pkDef);
        converted = converted.replaceAll("(?i)USING\\s+\\w+", "");
        converted = converted.replaceAll("(?i)PRIMARY KEY\\s*\\(([^)]+)\\)",
                "CONSTRAINT \"primary\" PRIMARY KEY ($1)");
        return converted;
    }

    /**
     * 转换唯一约束
     */
    private String convertUniqueConstraint(String uniqueDef) {
        String converted = removeBackticks(uniqueDef);
        converted = converted.replaceAll("(?i)USING\\s+\\w+", "");

        // 处理UNIQUE KEY和UNIQUE约束
        Pattern pattern = Pattern.compile(
                "(?:UNIQUE\\s+(?:KEY\\s+)?(?:`?(\\w+)`?\\s+)?)\\s*\\(([^)]+)\\)",
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher = pattern.matcher(converted);

        if (matcher.find()) {
            String constraintName = matcher.group(1);
            String columns = matcher.group(2);

            // 如果没有指定约束名，使用默认命名规则
            if (constraintName == null || constraintName.isEmpty()) {
                constraintName = "uq_" + columns.replaceAll("[,\\s]+", "_").replaceAll("[^\\w]", "");
            }

            columns = columns.replaceAll("`", "").replaceAll("\\(\\d+\\)", "");
            columns = escapeKeywordsInColumnList(columns);

            // 两种转换方式选其一：
            // 方式1: 转换为UNIQUE约束
            return "CONSTRAINT \"" + constraintName + "\" UNIQUE (" + columns + ")";

            // 方式2: 转换为唯一索引
            // return "CREATE UNIQUE INDEX " + constraintName + " ON " + tableName + " (" + columns + ")";
        }

        return converted;
    }


    /**
     * 转换检查约束
     */
    private String convertCheckConstraint(String checkDef) {
        String converted = removeBackticks(checkDef);
        converted = converted.replaceAll("(?i)USING\\s+\\w+", "");

        // 提取CHECK约束条件和可选的约束名
        Pattern pattern = Pattern.compile("(?:CONSTRAINT\\s+`?(\\w+)`?\\s+)?CHECK\\s*\\((.+)\\)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(converted);

        if (matcher.find()) {
            String constraintName = matcher.group(1);
            String checkCondition = matcher.group(2);

            if (constraintName != null && !constraintName.isEmpty()) {
                return "CONSTRAINT \"" + constraintName + "\" CHECK (" + checkCondition + ")";
            } else {
                return "CHECK (" + checkCondition + ")";
            }
        }

        return converted;
    }

    /**
     * 转换命名约束
     */
    private String convertNamedConstraint(String constraintDef) {
        String converted = removeBackticks(constraintDef);
        converted = converted.replaceAll("(?i)USING\\s+\\w+", "");

        // 处理命名约束（可能包含各种约束类型）
        Pattern pattern = Pattern.compile("CONSTRAINT\\s+`?(\\w+)`?\\s+((?:PRIMARY KEY|UNIQUE|CHECK|FOREIGN KEY).+)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(converted);

        if (matcher.find()) {
            String constraintName = matcher.group(1);
            String constraintBody = matcher.group(2);

            // 根据约束类型分别处理
            if (constraintBody.toUpperCase().startsWith("PRIMARY KEY")) {
                return "CONSTRAINT \"" + constraintName + "\" PRIMARY KEY " +
                        constraintBody.substring("PRIMARY KEY".length());
            } else if (constraintBody.toUpperCase().startsWith("UNIQUE")) {
                return "CONSTRAINT \"" + constraintName + "\" UNIQUE " +
                        constraintBody.substring("UNIQUE".length());
            } else if (constraintBody.toUpperCase().startsWith("CHECK")) {
                return "CONSTRAINT \"" + constraintName + "\" CHECK " +
                        constraintBody.substring("CHECK".length());
            } else if (constraintBody.toUpperCase().startsWith("FOREIGN KEY")) {
                // 外键约束需要在表创建后单独处理
                return ""; // 暂时跳过，后续通过ALTER TABLE处理
            }
        }

        return converted;
    }

    /**
     * 转换INSERT语句
     */
    private String convertInsertStatement(String sql) {
        String converted = removeBackticks(sql);
        converted = converted.replaceAll("b'0'", "'0'");
        converted = converted.replaceAll("b'1'", "'1'");
        converted = converted.replaceAll("(?i)NOW\\(\\)", "CURRENT_TIMESTAMP");
        converted = replaceBinaryWithEmptyString(converted);

        return converted;
    }

    private String replaceBinaryWithEmptyString(String sql) {
        StringBuilder result = new StringBuilder();
        int i = 0;
        int len = sql.length();

        while (i < len) {
            // 查找 ,_binary 的位置
            int binaryStart = sql.indexOf(",_binary", i);
            if (binaryStart == -1) {
                result.append(sql.substring(i));
                break;
            }

            // 添加 ,_binary 之前的内容
            result.append(sql.substring(i, binaryStart));
            result.append(",''"); // 替换为 ,''

            // 跳过 ,_binary
            i = binaryStart + 8; // 8是 ",_binary" 的长度

            // 跳过空白字符
            while (i < len && Character.isWhitespace(sql.charAt(i))) {
                i++;
            }

            // 如果下一个字符是单引号，我们需要找到匹配的结束单引号
            if (i < len && sql.charAt(i) == '\'') {
                i++; // 跳过开头的单引号

                // 查找结束单引号，处理转义情况
                boolean inEscape = false;
                while (i < len) {
                    char c = sql.charAt(i);

                    if (inEscape) {
                        inEscape = false;
                        i++;
                        continue;
                    }

                    if (c == '\\') {
                        inEscape = true;
                        i++;
                        continue;
                    }

                    if (c == '\'') {
                        // 找到结束单引号
                        i++; // 跳过结束单引号

                        // 检查后面是否是逗号或右括号
                        while (i < len && Character.isWhitespace(sql.charAt(i))) {
                            i++;
                        }

                        if (i < len && (sql.charAt(i) == ',' || sql.charAt(i) == ')')) {
                            // 这是完整的 _binary 字段，我们已经处理完了
                            break;
                        }
                        // 否则继续查找下一个单引号
                    }

                    i++;
                }
            }
        }

        return result.toString();
    }

    /**
     * 转换DROP TABLE语句
     */
    private String convertDropTable(String sql) {
        String converted = removeBackticks(sql);
        // 提取表名并转义
        Pattern dropTablePattern = Pattern.compile("DROP TABLE\\s+(?:IF EXISTS\\s+)?(.+)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = dropTablePattern.matcher(converted);
        if (matcher.find()) {
            String tableName = matcher.group(1).trim();
            String escapedTableName = escapeKeyword(tableName);
            converted = converted.replace(tableName, escapedTableName);
        }
        if (!converted.toUpperCase().contains("IF EXISTS")) {
            converted = converted.replaceFirst("(?i)DROP TABLE", "DROP TABLE IF EXISTS");
        }
        return converted;
    }

    /**
     * 转换ALTER TABLE语句
     */
    private String convertAlterTable(String sql) {
        String converted = removeBackticks(sql);
        // 表名关键字转义
        Pattern alterTablePattern = Pattern.compile("ALTER TABLE\\s+(.+?)(\\s|$)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = alterTablePattern.matcher(converted);
        if (matcher.find()) {
            String tableName = matcher.group(1).trim();
            String escapedTableName = escapeKeyword(tableName);
            converted = converted.replaceFirst(Pattern.quote(tableName), escapedTableName);
        }
        converted = removeCharsetAndCollate(converted);
        converted = converted.replaceAll("(?i)ON UPDATE CURRENT_TIMESTAMP", "");
        converted = converted.replaceAll("(?i)USING\\s+\\w+", "");

        // 处理ALTER TABLE添加约束
        converted = convertAlterTableConstraints(converted);

        return converted;
    }

    /**
     * 转换ALTER TABLE约束
     */
    private String convertAlterTableConstraints(String sql) {
        String converted = sql;

        // 处理ADD CONSTRAINT
        Pattern addConstraintPattern = Pattern.compile("ADD\\s+CONSTRAINT\\s+`?(\\w+)`?\\s+", Pattern.CASE_INSENSITIVE);
        Matcher matcher = addConstraintPattern.matcher(converted);

        if (matcher.find()) {
            // 确保使用正确的ADD CONSTRAINT语法
            converted = converted.replaceAll("(?i)ADD\\s+CONSTRAINT", "ADD CONSTRAINT");
        }

        // 处理DROP CONSTRAINT
        Pattern dropConstraintPattern = Pattern.compile("DROP\\s+CONSTRAINT\\s+`?(\\w+)`?", Pattern.CASE_INSENSITIVE);
        matcher = dropConstraintPattern.matcher(converted);

        if (matcher.find()) {
            // 确保使用正确的DROP CONSTRAINT语法
            converted = converted.replaceAll("(?i)DROP\\s+CONSTRAINT", "DROP CONSTRAINT");

            // 添加IF EXISTS以避免约束不存在时报错
            if (!converted.toUpperCase().contains("IF EXISTS")) {
                converted = converted.replaceFirst("(?i)DROP CONSTRAINT", "DROP CONSTRAINT IF EXISTS");
            }
        }

        return converted;
    }

    /**
     * 转换通用SQL语句
     */
    private String convertGenericSQL(String sql) {
        String converted = removeBackticks(sql);
        converted = removeCharsetAndCollate(converted);
        converted = converted.replaceAll("(?i)ON UPDATE CURRENT_TIMESTAMP", "");
        converted = converted.replaceAll("(?i)USING\\s+\\w+", "");
        return converted;
    }

    /**
     * 移除反引号
     */
    private String removeBackticks(String sql) {
        return sql.replaceAll("`", "");
    }

    /**
     * 分割列定义
     */
    private List<String> splitColumnDefinitions(String columnDefs) {
        List<String> parts = new ArrayList<>();
        StringBuilder current = new StringBuilder();
        int parenCount = 0;
        boolean inString = false;
        char stringChar = '\'';

        for (int i = 0; i < columnDefs.length(); i++) {
            char c = columnDefs.charAt(i);

            if (!inString) {
                if (c == '(') parenCount++;
                else if (c == ')') parenCount--;
            }

            if (c == '\'' || c == '"') {
                if (!inString) {
                    inString = true;
                    stringChar = c;
                } else if (c == stringChar) {
                    if (i > 0 && columnDefs.charAt(i-1) == '\\') {
                    } else {
                        inString = false;
                    }
                }
            }

            if (c == ',' && parenCount == 0 && !inString) {
                String part = current.toString().trim();
                if (!part.isEmpty()) {
                    parts.add(part);
                }
                current.setLength(0);
            } else {
                current.append(c);
            }
        }

        if (current.length() > 0) {
            String part = current.toString().trim();
            if (!part.isEmpty()) {
                parts.add(part);
            }
        }

        return parts;
    }


    /**
     * 判断是否为列定义
     */
    private boolean isColumnDefinition(String part) {
        return !part.toUpperCase().startsWith("PRIMARY KEY") &&
                !part.toUpperCase().startsWith("UNIQUE KEY") &&
                !part.toUpperCase().startsWith("UNIQUE") &&
                !part.toUpperCase().startsWith("CHECK") &&
                !part.toUpperCase().startsWith("CONSTRAINT") &&
                !part.toUpperCase().startsWith("KEY") &&
                !part.toUpperCase().startsWith("INDEX") &&
                !part.toUpperCase().startsWith("FOREIGN KEY");
    }

    /**
     * 查找匹配的括号
     */
    private int findMatchingParenthesis(String sql, int start) {
        int count = 1;
        boolean inString = false;
        char stringChar = '\'';

        for (int i = start + 1; i < sql.length(); i++) {
            char c = sql.charAt(i);

            if (!inString) {
                if (c == '(') count++;
                else if (c == ')') count--;
            }

            if (c == '\'' || c == '"') {
                if (!inString) {
                    inString = true;
                    stringChar = c;
                } else if (c == stringChar) {
                    if (i > 0 && sql.charAt(i-1) == '\\') {
                        continue;
                    }
                    inString = false;
                }
            }

            if (count == 0) return i;
        }
        return -1;
    }

    /**
     * 生成列注释语句
     */
    public List<String> generateColumnComments(String originalSQL) {
        List<String> comments = new ArrayList<>();

        if (originalSQL == null || !originalSQL.toUpperCase().contains("CREATE TABLE")) {
            return comments;
        }

        String cleanedSQL = removeBackticks(originalSQL);
        String tableName = extractTableName(cleanedSQL);
        String columnDefs = extractColumnDefinitions(cleanedSQL);

        if (columnDefs.isEmpty()) {
            return comments;
        }

        List<String> parts = splitColumnDefinitions(columnDefs);

        for (String part : parts) {
            String trimmed = part.trim();
            if (trimmed.isEmpty() || !isColumnDefinition(trimmed)) continue;

            String columnName = extractColumnName(trimmed);
            String comment = extractComment(trimmed);

            if (comment != null && !comment.isEmpty()) {
                String escapedColumnName = escapeKeyword(columnName);
                // 表名关键字转义
                comments.add("COMMENT ON COLUMN " + escapeKeyword(tableName) + "." + escapedColumnName + " IS '" + comment + "'");
            }
        }

        return comments;
    }

    /**
     * 为关键字添加双引号
     */
    private String escapeKeyword(String identifier) {
        if (identifier == null) return null;
        if (kwdbKeywords.contains(identifier.toLowerCase())) {
            return "\"" + identifier + "\"";
        }
        return identifier;
    }

    /**
     * 生成索引语句
     */
    public List<String> generateIndexStatements(String originalSQL) {
        List<String> indexStatements = new ArrayList<>();

        if (originalSQL == null || !originalSQL.toUpperCase().contains("CREATE TABLE")) {
            return indexStatements;
        }

        String cleanedSQL = removeBackticks(originalSQL);
        String tableName = extractTableName(cleanedSQL);
        String columnDefs = extractColumnDefinitions(cleanedSQL);

        if (columnDefs.isEmpty()) {
            return indexStatements;
        }

        List<String> parts = splitColumnDefinitions(columnDefs);

        for (String part : parts) {
            String trimmed = part.trim();
            if (trimmed.isEmpty()) continue;

            if (trimmed.toUpperCase().startsWith("FULLTEXT KEY")) {
                String indexSQL = convertFulltextIndex(trimmed, tableName);
                if (!indexSQL.isEmpty()) {
                    indexStatements.add(indexSQL);
                }
            } else if ((trimmed.toUpperCase().startsWith("INDEX") || trimmed.toUpperCase().startsWith("KEY")) &&
                    !trimmed.toUpperCase().startsWith("UNIQUE")) {
                String indexSQL = convertIndexDefinition(trimmed, tableName);
                if (!indexSQL.isEmpty()) {
                    indexStatements.add(indexSQL);
                }
            }
        }

        return indexStatements;
    }


    /**
     * 转换FULLTEXT索引为普通索引
     */
    private String convertFulltextIndex(String fulltextDef, String tableName) {
        String cleaned = removeBackticks(fulltextDef);
        cleaned = cleaned.replaceAll("(?i)USING\\s+\\w+", "");

        Pattern pattern = Pattern.compile("FULLTEXT\\s+(?:KEY\\s+)?(`?(\\w+)`?)?\\s*\\(([^)]+)\\)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(cleaned);

        if (matcher.find()) {
            String indexName = matcher.group(2);
            String columns = matcher.group(3);

            if (indexName == null || indexName.isEmpty()) {
                String firstColumn = columns.split(",")[0].trim().replaceAll("`", "").split("\\s+")[0];
                indexName = tableName + "_" + firstColumn + "_idx";
            }

            columns = columns.replaceAll("`", "").replaceAll("\\(\\d+\\)", "");
            columns = escapeKeywordsInColumnList(columns);

            return "CREATE INDEX " + indexName + " ON " + escapeKeyword(tableName) + " (" + columns + ")";
        }

        return "";
    }


    /**
     * 转换索引定义
     */
    private String convertIndexDefinition(String indexDef, String tableName) {
        String cleaned = removeBackticks(indexDef);
        cleaned = cleaned.replaceAll("(?i)USING\\s+\\w+", "");

        Pattern pattern = Pattern.compile("(?:KEY|INDEX)\\s*(`?(\\w+)`?)?\\s*\\(([^)]+)\\)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(cleaned);

        if (matcher.find()) {
            String indexName = matcher.group(2);
            String columns = matcher.group(3);

            if (indexName == null || indexName.isEmpty()) {
                String firstColumn = columns.split(",")[0].trim().replaceAll("`", "").split("\\s+")[0];
                indexName = tableName + "_" + firstColumn + "_idx";
            }

            columns = columns.replaceAll("`", "").replaceAll("\\(\\d+\\)", "");
            columns = escapeKeywordsInColumnList(columns);

            return "CREATE INDEX " + indexName + " ON " + escapeKeyword(tableName) + " (" + columns + ")";
        }

        return "";
    }

    /**
     * 处理列列表中的关键字
     */
    private String escapeKeywordsInColumnList(String columns) {
        List<String> columnList = new ArrayList<>();
        String[] columnArray = columns.split(",");

        for (String column : columnArray) {
            String trimmed = column.trim();
            String columnName = trimmed.split("\\s+")[0];

            if (kwdbKeywords.contains(columnName.toLowerCase())) {
                String escapedColumn = "\"" + columnName + "\"" + trimmed.substring(columnName.length());
                columnList.add(escapedColumn);
            } else {
                columnList.add(trimmed);
            }
        }

        return String.join(", ", columnList);
    }

    /**
     * 提取列名
     */
    private String extractColumnName(String columnDef) {
        String[] parts = columnDef.split("\\s+");
        return parts.length > 0 ? parts[0].replaceAll("[\"']", "") : "";
    }

    /**
     * 提取注释内容
     */
    private String extractComment(String columnDef) {
        Pattern pattern = Pattern.compile("(?i)COMMENT\\s+'(.*?)'");
        Matcher matcher = pattern.matcher(columnDef);
        return matcher.find() ? matcher.group(1) : null;
    }

    /**
     * 生成外键约束语句
     */
    public List<String> generateForeignKeyStatements(String originalSQL) {
        List<String> foreignKeyStatements = new ArrayList<>();

        if (originalSQL == null || !originalSQL.toUpperCase().contains("CREATE TABLE")) {
            return foreignKeyStatements;
        }

        String cleanedSQL = removeBackticks(originalSQL);
        String tableName = extractTableName(cleanedSQL);
        String columnDefs = extractColumnDefinitions(cleanedSQL);

        if (columnDefs.isEmpty()) {
            return foreignKeyStatements;
        }

        List<String> parts = splitColumnDefinitions(columnDefs);

        for (String part : parts) {
            String trimmed = part.trim();
            if (trimmed.isEmpty()) continue;

            if (trimmed.toUpperCase().contains("FOREIGN KEY")) {
                String foreignKeySQL = convertForeignKeyDefinition(trimmed, tableName);
                if (!foreignKeySQL.isEmpty()) {
                    foreignKeyStatements.add(foreignKeySQL);
                }
            }
        }

        return foreignKeyStatements;
    }

    /**
     * 转换外键定义
     */
    private String convertForeignKeyDefinition(String foreignKeyDef, String tableName) {
        String cleaned = removeBackticks(foreignKeyDef);

        // 提取外键约束的详细信息
        Pattern pattern = Pattern.compile(
                "(?:CONSTRAINT\\s+`?(\\w+)`?\\s+)?FOREIGN KEY\\s*\\(([^)]+)\\)\\s*REFERENCES\\s+`?(\\w+)`?\\s*\\(([^)]+)\\)(?:\\s+ON\\s+DELETE\\s+(RESTRICT|CASCADE|SET NULL|SET DEFAULT|NO ACTION))?(?:\\s+ON\\s+UPDATE\\s+(RESTRICT|CASCADE|SET NULL|SET DEFAULT|NO ACTION))?",
                Pattern.CASE_INSENSITIVE
        );

        Matcher matcher = pattern.matcher(cleaned);

        if (matcher.find()) {
            String constraintName = matcher.group(1);
            String foreignKeyColumns = matcher.group(2);
            String referencedTable = matcher.group(3);
            String referencedColumns = matcher.group(4);
            String onDelete = matcher.group(5);
            String onUpdate = matcher.group(6);

            if (constraintName == null || constraintName.isEmpty()) {
                String firstColumn = foreignKeyColumns.split(",")[0].trim();
                constraintName = tableName + "_" + firstColumn + "_fk";
            }

            // 构建ALTER TABLE语句
            StringBuilder alterTable = new StringBuilder();
            alterTable.append("ALTER TABLE ").append(escapeKeyword(tableName))
                    .append(" ADD CONSTRAINT \"").append(constraintName).append("\"")
                    .append(" FOREIGN KEY (").append(foreignKeyColumns).append(")")
                    .append(" REFERENCES ").append(escapeKeyword(referencedTable))
                    .append(" (").append(referencedColumns).append(")");

            if (onDelete != null && !onDelete.isEmpty()) {
                alterTable.append(" ON DELETE ").append(onDelete);
            }

            if (onUpdate != null && !onUpdate.isEmpty()) {
                alterTable.append(" ON UPDATE ").append(onUpdate);
            }

            return alterTable.toString();
        }

        return "";
    }

    /**
     * SQL转换异常
     */
    public static class SQLConversionException extends RuntimeException {
        public SQLConversionException(String message) {
            super(message);
        }

        public SQLConversionException(String message, Throwable cause) {
            super(message, cause);
        }
    }
}